# frozen_string_literal: true

require 'wpxf/models/module'

module Wpxf
  module Cli
    # Methods for handling commands that provide the user with help info.
    module Help
      def print_options(mod)
        print_std 'Module options:'
        puts
        indent_cursor do
          print_options_table(mod, module_options(mod, false))
        end
      end

      def print_payload_options(payload)
        print_std 'Payload options:'
        puts
        indent_cursor do
          print_options_table(payload, payload.options)
        end
      end

      def show_options
        return unless module_loaded?(false)

        print_options(context.module)
        return unless context.module.payload

        puts
        print_payload_options(context.module.payload)
      end

      def print_options_table(mod, opts)
        data = empty_option_table_data
        opts.each do |opt|
          data.push(option_table_row(mod, opt))
        end

        print_table(data)
      end

      def print_advanced_option(mod, opt)
        print_std "Name: #{opt.name}"
        print_std "Current setting: #{mod.normalized_option_value(opt.name)}"
        print_std "Required: #{opt.required?}"
        print_std "Description: #{opt.desc}"
      end

      def show_advanced_options
        return unless module_loaded?(false)

        module_options(context.module, true).each do |opt|
          print_advanced_option(context.module, opt)
          puts
        end
      end

      def help
        commands_file = Wpxf::DataFile.new('json', 'commands.json')
        data = JSON.parse(commands_file.content)['data']
        data.unshift('cmd' => 'Command', 'desc' => 'Description')
        print_table data
      end

      def show_exploits
        modules = Wpxf::Models::Module.where(type: 'exploit')
                                .order(:path)
                                .map { |m| { path: m.path, title: m.name } }

        print_good "#{modules.length} Exploits"
        print_module_table modules
      end

      def show_auxiliary
        modules = Wpxf::Models::Module.where(type: 'auxiliary')
                                .order(:path)
                                .map { |m| { path: m.path, title: m.name } }

        print_good "#{modules.length} Auxiliaries"
        print_module_table modules
      end

      def show(target)
        handlers = {
          'options' => 'show_options',
          'advanced' => 'show_advanced_options',
          'exploits' => 'show_exploits',
          'auxiliary' => 'show_auxiliary'
        }

        if handlers[target]
          send(handlers[target])
        else
          print_bad("\"#{target}\" is not a valid argument")
        end
      end

      def module_options(mod, advanced)
        return [] if mod.nil?
        opts = mod.options.select { |o| o.advanced? == advanced }
        opts.sort_by(&:name)
      end

      def empty_option_table_data
        [{
          name: 'Name',
          value: 'Current Setting',
          req: 'Required',
          desc: 'Description'
        }]
      end

      def option_table_row(mod, opt)
        {
          name: opt.name,
          value: mod.normalized_option_value(opt.name),
          req: opt.required?,
          desc: opt.desc
        }
      end
    end
  end
end
